package org.zhadoop.stream.cql.semanticanalyzer;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zhadoop.stream.api.streams.Schema;
import org.zhadoop.stream.cql.exception.SemanticAnalyzerException;
import org.zhadoop.stream.cql.semanticanalyzer.analyzecontext.AnalyzeContext;
import org.zhadoop.stream.cql.semanticanalyzer.analyzecontext.FromClauseAnalyzeContext;
import org.zhadoop.stream.cql.semanticanalyzer.analyzecontext.ParallelClauseAnalyzeContext;
import org.zhadoop.stream.cql.semanticanalyzer.analyzecontext.SelectAnalyzeContext;
import org.zhadoop.stream.cql.semanticanalyzer.analyzecontext.SelectClauseAnalyzeContext;
import org.zhadoop.stream.cql.semanticanalyzer.parser.context.ParseContext;
import org.zhadoop.stream.cql.semanticanalyzer.parser.context.SelectStatementContext;
import org.zhadoop.streaming.exception.ErrorCode;

/**
 * select 语法分析
 * @author zwd
 *
 */
public class SelectStatementAnalyzer extends BaseAnalyzer {

	private static final Logger LOG = LoggerFactory.getLogger(SelectStatementAnalyzer.class);
	
	private SelectAnalyzeContext context;
	
	private SelectStatementContext selectContext;
	
	private String outputStreamName = null;
	
	public SelectStatementAnalyzer(ParseContext parseContext) throws SemanticAnalyzerException {
		super(parseContext);
		selectContext = (SelectStatementContext) parseContext;
	}

	@Override
	public void init(List<Schema> schemas) throws SemanticAnalyzerException {
		// TODO Auto-generated method stub

	}

	@Override
	public AnalyzeContext analyze() throws SemanticAnalyzerException {
		fromAnalyzer();
        selectAnalyzer();
        resetOutputColumnTypes();
        whereAnalyzer();
        groupbyAnalyzer();
        havingAnalyzer();
        orderByAnalyzer();
        limitAnalyzer();
        parallelAnalyzer();
        dataSourceQueryArgumentsAnalyzer();
        return context;
	}

	private void selectAnalyzer() throws SemanticAnalyzerException{
		SemanticAnalyzer analyzer = 
				SemanticAnalyzerFactory.createAnalyzer(selectContext.getSelect(), getInputSchemas());
		context.setSelectClauseContext((SelectClauseAnalyzeContext) analyzer.analyze());
	}

	private List<Schema> getInputSchemas() throws SemanticAnalyzerException{
		if(context.getFromClauseContext() == null){
			LOG.error("'{}' was not parsed.", "from clause");
            SemanticAnalyzerException exception = new SemanticAnalyzerException(ErrorCode.UNKNOWN_SERVER_COMMON_ERROR);
            throw exception;
		}
		return context.getFromClauseContext().getInputSchemas();
	}

	private void havingAnalyzer() {
		// TODO Auto-generated method stub
	}

	private void whereAnalyzer() {
		// TODO Auto-generated method stub
	}

	private void resetOutputColumnTypes() {
		// TODO Auto-generated method stub
	}

	private void groupbyAnalyzer() {
		// TODO Auto-generated method stub
	}

	private void orderByAnalyzer() {
		// TODO Auto-generated method stub
	}

	private void limitAnalyzer() {
		// TODO Auto-generated method stub
	}

	private void dataSourceQueryArgumentsAnalyzer() {
		// TODO Auto-generated method stub
	}

	private void fromAnalyzer() throws SemanticAnalyzerException{
		SemanticAnalyzer analyzer = SemanticAnalyzerFactory.createAnalyzer(selectContext.getFrom(), getAllSchemas());
		context.setFromClauseContext((FromClauseAnalyzeContext)analyzer.analyze());
	}

	private void parallelAnalyzer() throws SemanticAnalyzerException{
		if(selectContext.getParallel() == null){
			return;
		}
		
		SemanticAnalyzer analyzer = SemanticAnalyzerFactory.createAnalyzer(selectContext.getParallel(),null);
		context.setParallelClauseContext((ParallelClauseAnalyzeContext)analyzer.analyze());
	}

	@Override
	protected AnalyzeContext getAnalyzeContext() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	protected void createAnalyzeContext() {
		// TODO Auto-generated method stub
		
	}

	public SelectAnalyzeContext getContext() {
		return context;
	}

	public void setContext(SelectAnalyzeContext context) {
		this.context = context;
	}

	public SelectStatementContext getSelectContext() {
		return selectContext;
	}

	public void setSelectContext(SelectStatementContext selectContext) {
		this.selectContext = selectContext;
	}

	public String getOutputStreamName() {
		return outputStreamName;
	}

	public void setOutputStreamName(String outputStreamName) {
		this.outputStreamName = outputStreamName;
	}
	
}
